<script setup>
// import axios from "@/utils/request";
import { reactive, watch, onMounted } from "vue";

const props = defineProps({
  id: String,
  data: Array,
  divideCount: Number,
  operateType: String,
});

const rectColorMap = new Map();
rectColorMap.set(1, "#EFF7FF");
rectColorMap.set(2, "#FFE9E9");
rectColorMap.set(3, "#b3e19d");

const borderColorMap = new Map();
borderColorMap.set(1, "#3E8FF7");
borderColorMap.set(2, "#FB602D");
borderColorMap.set(3, "#67C23A");

const info = reactive({
  width: 800,
  height: 320,
  divideCount: props.divideCount || 10,
  ctx: null,
  bkDirection: "right",
  points: [],
  rects: [],
  originSource: [],
  triangles: {},
  dynamicRects: {},
  dynamicTriangles: {},
  rectTexts: {},
  titleTexts: {},
  tagTexts: {},
  tags: {},
  arcRadius: 0,
  triangleColor: "#62a4f9",
  data: [],
  raf: null,
  steps: 100, // 一格之间的点位数量
  pathEndY: 0,
  pathStartY: 0,
  arcLocationY: 0,
  backgroundPoints: [],
  index: 0,
  circleCount: 1,
  radius: 0,
  halfRadius: 0,
  curLocation: undefined,
  curParts: "",
});
// 格子的直径
// const radius = info.width / info.divideCount / 1.5
// 格子的半径
// const halfRadius = radius / 2

// info.height = radius * 4 + 80

const drawArc = (options) => {
  let endPath;

  if (options.direct === "right") {
    endPath = -0.5 + options.step;
  }
  if (options.direct === "left") {
    endPath = options.beginPath + options.step;
  }

  var lastX =
    options.startX + info.arcRadius * Math.cos((endPath - 0.01) * Math.PI);
  var lastY =
    options.startY + info.arcRadius * Math.sin((endPath - 0.01) * Math.PI);
  let curX = options.startX + info.arcRadius * Math.cos(endPath * Math.PI);
  let curY = options.startY + info.arcRadius * Math.sin(endPath * Math.PI);

  const target = {
    startX: lastX,
    startY: lastY,
    endX: curX,
    endY: curY,
  };
  return target;
};

const clear = () => {
  info.ctx?.clearRect(0, 0, info.width, info.height);
};

const drawArrow2 = (x, y, color, direct) => {
  info.ctx.beginPath();
  let size = (1 / 8) * info.radius;
  if (direct === "down") {
    info.ctx.moveTo(x - size, y);
    info.ctx.lineTo(x, y + size);
    info.ctx.lineTo(x + size, y);
  }
  if (direct === "up") {
    info.ctx.moveTo(x - size, y);
    info.ctx.lineTo(x, y - size);
    info.ctx.lineTo(x + size, y);
  }

  info.ctx.fillStyle = color;
  info.ctx.closePath();
  info.ctx.fill();
};

function drawArrow(x, y) {
  info.ctx.beginPath();
  info.ctx.arc(x, y, 8, 0, 2 * Math.PI);

  info.ctx.fillStyle = borderColorMap.get(info.circleCount) || "#4b90ff";
  info.ctx.closePath();
  info.ctx.fill();
}

const drawText = (item) => {
  info.ctx.font = `${item.fontSize || 16}px Arial`;
  info.ctx.fillStyle = item.fillStyle || "#000";
  info.ctx.fillText(item.text, item.startX, item.startY + info.radius / 2);
};

/**
 *
 * @param {*} item 矩形信息
 * @param {*} radius 圆角大小
 */
const drawRect = (item, radius = 8) => {
  if (!item) return;
  info.ctx.fillStyle = item.fillStyle;
  info.ctx.strokeStyle = item.strokeStyle;
  info.ctx.beginPath();
  info.ctx.moveTo(item.startX + radius, item.startY);
  info.ctx.lineTo(item.startX + item.endX - radius, item.startY);
  info.ctx.quadraticCurveTo(
    item.startX + item.endX,
    item.startY,
    item.startX + item.endX,
    item.startY + radius
  );
  info.ctx.lineTo(item.startX + item.endX, item.startY + item.endY - radius);
  info.ctx.quadraticCurveTo(
    item.startX + item.endX,
    item.startY + item.endY,
    item.startX + item.endX - radius,
    item.startY + item.endY
  );
  info.ctx.lineTo(item.startX + radius, item.startY + item.endY);
  info.ctx.quadraticCurveTo(
    item.startX,
    item.startY + item.endY,
    item.startX,
    item.startY + item.endY - radius
  );
  info.ctx.lineTo(item.startX, item.startY + radius);
  info.ctx.quadraticCurveTo(
    item.startX,
    item.startY,
    item.startX + radius,
    item.startY
  );
  info.ctx.closePath();

  // info.ctx.shadowColor = '#e0e0e0'
  // info.ctx.shadowOffsetX = 2
  // info.ctx.shadowOffsetY = 2
  // info.ctx.shadowBlur = 8

  info.ctx.fill();
  info.ctx.strokeStyle = item.strokeStyle; // 这里的 'blue' 可以替换成任何你想要的颜色
  info.ctx.lineWidth = 1; // 这里的 2 可以替换成任何你想要的边框宽度
  info.ctx.stroke();

  // info.ctx.shadowOffsetX = 0
  // info.ctx.shadowOffsetY = 0
  // info.ctx.shadowBlur = 0
};

// 背景线
const drawLine = (ctx, points, options) => {
  points.forEach((item) => {
    if (!item) return;
    ctx.beginPath();
    ctx.lineWidth = options?.lineWidth || 5;
    ctx.lineCap = "round";
    ctx.moveTo(item.startX - 0.5, item.startY);
    ctx.lineTo(item.endX + 0.5, item.endY);

    ctx.strokeStyle = options?.strokeStyle || "#4b90ff";
    ctx.stroke();
  });
};

const drawDynamicLine = (ctx, points, options) => {
  // 16.6667ms
  if (info.index < points.length) {
    // 更改路径速度
    info.index = info.index + 2;
  }
  // 最大圈数跑完 颜色重置
  if (info.circleCount > info.maxCircle) {
    info.index = 0;
    info.circleCount = 1;

    for (let tIdx in info.rects) {
      info.rects[tIdx].fillStyle = "#fff";
      info.rects[tIdx].strokeStyle = "#fff";
      info.triangles[tIdx].strokeStyle = "#fff";
      info.triangles[tIdx].fillStyle = "#fff";
      info.rectTexts[tIdx].fillStyle = "transparent";
    }
  }
  // 一圈重置
  if (points && points.length && info.index >= points.length) {
    info.index = 0;
    info.circleCount++;
  }

  // 动态路径的点位集合
  info.originSource = points.slice(0, info.index);
  // 大圆点
  const tPoint = points[info.index];
  tPoint && drawArrow(tPoint.endX, tPoint.endY);

  // 动态格子 三角形
  if (tPoint && tPoint.changeStyle) {
    const targetData = info.data[tPoint.rectIdx];

    // const changeFlag = targetData.circle.includes(info.circleCount)
    const changeFlag = targetData.proOfCircleVOList.some(
      (item) => +item.circle === +info.circleCount
    );

    if (changeFlag) {
      const curRectColor = rectColorMap.get(info.circleCount);
      const curBorderColor = borderColorMap.get(info.circleCount);
      // 格子
      info.rects[tPoint.rectIdx].fillStyle = curRectColor;
      info.rects[tPoint.rectIdx].strokeStyle = curBorderColor;
      // 三角形
      info.triangles[tPoint.rectIdx].strokeStyle = curBorderColor;
      info.triangles[tPoint.rectIdx].fillStyle = curBorderColor;
      // 格子文字
      info.rectTexts[tPoint.rectIdx].fillStyle = curBorderColor;

      //
      const t = info.data[tPoint.rectIdx].proOfCircleVOList.filter(
        (item) => +item.circle === +info.circleCount
      );
      if (t) {
        const flag = t.length > 1;
        const text = flag ? t[0].sortField + "..." : t?.[0].sortField;

        info.curLocation = info.data[tPoint.rectIdx].stationNo; // 当前站位
        info.rectTexts[tPoint.rectIdx].text = text;
        info.curParts = t.reduce((prev, item) => {
          return !prev ? `${item.sortField}` : prev + `,${item.sortField}`;
        }, "");

        info.rectTexts[tPoint.rectIdx].adjust = true;
        // 移动格子文字的横坐标位置
        if (!info.rectTexts[tPoint.rectIdx].adjust) {
          info.rectTexts[tPoint.rectIdx].startX = flag
            ? info.rectTexts[tPoint.rectIdx].startX - 0.2
            : info.rectTexts[tPoint.rectIdx].startX;
        }
      }
    }
  }

  info.originSource.forEach((item) => {
    if (!item) return;
    ctx.beginPath();
    ctx.lineWidth = options?.lineWidth || 5;
    ctx.lineCap = "round";
    ctx.moveTo(item.startX - 0.5, item.startY);
    ctx.lineTo(item.endX + 0.5, item.endY);

    ctx.strokeStyle = borderColorMap.get(info.circleCount);
    // ctx.strokeStyle = options?.strokeStyle || '#4b90ff'
    ctx.stroke();
  });
};

const animate = () => {
  clear();
  info.raf = requestAnimationFrame(animate);

  // 静态箭头
  for (let item in info.triangles) {
    item &&
      drawArrow2(
        info.triangles[item].x,
        info.triangles[item].y,
        info.triangles[item].fillStyle,
        info.triangles[item].direct
      );
  }
  //动态箭头
  // for (let item in info.dynamicTriangles) {
  // item &&
  //   drawArrow2(
  //     info.dynamicTriangles[item].x,
  //     info.dynamicTriangles[item].y,
  //     info.dynamicTriangles[item].fillStyle,
  //     info.dynamicTriangles[item].direct
  //   )
  // }
  // 格子
  for (let item in info.rects) {
    item && drawRect(info.rects[item], 4);
  }
  // 背景线
  drawLine(info.ctx, info.backgroundPoints, {
    strokeStyle: "#fff",
    lineWidth: 8,
  });
  // 工序文字处理
  for (let item in info.rectTexts) {
    item && drawText(info.rectTexts[item]);
  }
  // 站位背景框处理
  for (let item in info.tags) {
    const target = info.tags[item];
    const strokeStyle = info.rects[item].strokeStyle;
    target.fillStyle = ["#fff", "#ffffff"].includes(strokeStyle)
      ? "#3E8FF7"
      : strokeStyle;
    target.strokeStyle = target.fillStyle;
    item && drawRect(info.tags[item], 4);
  }
  // 站位文字处理
  for (let item in info.tagTexts) {
    item && drawText(info.tagTexts[item]);
  }
  // 动态线
  if (info.backgroundPoints && info.backgroundPoints.length) {
    drawDynamicLine(info.ctx, info.backgroundPoints, {
      strokeStyle: "#4b90ff",
      lineWidth: 4,
    });
  }
};

const getPartLen = (count) => {
  if (count > 99) return 3;
  if (count > 9) return 2;
  return 1;
};

const drawInitBackgroundLine = () => {
  info.data.forEach((item, idx) => {
    const target = item.stationNo;
    // 字号处理
    // const fontFlag = target >= 10
    const textInfo = {
      startX: item.x + info.halfRadius,
      startY: item.y + 8,
      text: target,
      // fontSize: fontFlag ? 14 : 16,
      fontSize: info.radius <= 40 ? 12 : info.radius <= 60 ? 14 : 16,
      fillStyle: "transparent",
    };
    // 文字长度
    const partsLen = getPartLen(item);
    if (partsLen === 1) {
      textInfo.startX = item.x + info.halfRadius - 4;
    }
    if (partsLen === 2 && item.parts.length === 2) {
      textInfo.startX = item.x + info.halfRadius - textInfo.fontSize + 4;
    }
    if (partsLen === 2 && item.parts.length === 1) {
      textInfo.startX = item.x + info.halfRadius - textInfo.fontSize / 2;
    }
    if (partsLen === 3) {
      textInfo.startX = item.x + info.halfRadius - textInfo.fontSize;
    }
    if (partsLen === 4) {
      textInfo.startX = item.x + info.halfRadius - textInfo.fontSize - 4;
    }

    info.rectTexts[idx] = textInfo;

    let startX, endX, distanceX;
    if (idx > 0) {
      startX = info.data[idx - 1].x + info.halfRadius;
    }
    if (idx === 0) {
      startX = info.data[idx].x + info.halfRadius;
    }

    endX = item.x + info.halfRadius;
    for (let i = 0; i < info.steps; i++) {
      // 箭头运动方向
      if (idx < info.divideCount) {
        info.bkDirection = "right";
      }
      if (idx % info.divideCount === 0 && idx % (2 * info.divideCount) !== 0) {
        info.bkDirection = "down";
      }
      if (idx > info.divideCount) {
        info.bkDirection = "left";
      }
      if (idx % (2 * info.divideCount) === 0 && idx !== 0) {
        info.bkDirection = "up";
      }
      distanceX = (endX - startX) / info.steps || 0;
      let point = {};
      if (info.bkDirection === "right") {
        point = {
          startX: startX,
          startY: info.pathStartY,
          endX: startX + distanceX * (i + 1),
          endY: info.pathStartY,
        };
      }
      if (info.bkDirection === "left") {
        point = {
          startX: startX,
          startY: info.pathEndY,
          endX: startX + distanceX * (i + 1),
          endY: info.pathEndY,
        };
      }
      // 获取圆心位置
      if (idx % info.divideCount === 0 && idx % (2 * info.divideCount) !== 0) {
        let t = {
          startX: startX - 4,
          startY: info.arcLocationY,
          radius: info.arcRadius,
          direct: "right",
          beginPath: 1.5,
          step: i / info.steps,
        };

        point = drawArc(t);
      }
      // 处理箭头路径的点
      if (point) {
        point.rectIdx = idx;
        point.changeStyle = info.rectTexts?.[idx]?.text ? true : false;
        info.backgroundPoints.push(point);
      }
    }
  });

  // 左侧半圆的点位
  let lastStartX = info.data.at(-1).x + info.halfRadius;
  for (let i = 0; i < info.steps; i++) {
    info.bkDirection = "up";
    let tp = {
      startX: lastStartX + 4,
      startY: info.arcLocationY,
      radius: info.arcRadius,
      direct: "left",
      beginPath: 0.5,
      step: i / info.steps,
    };
    const point = drawArc(tp);
    info.backgroundPoints.push(point);
  }
};

const init = () => {
  info.points = [];
  info.rects = {};
  info.dynamicRects = {};
  info.triangles = {};
  info.dynamicTriangles = {};
  info.backgroundPoints = [];
  info.originSource = [];
  info.rectTexts = {};
  info.titleTexts = {};
  info.tagTexts = {};
  info.tags = {};
  info.finish = false;
};

const initPathInfo = () => {
  if (!info.pathStartY && info.data && info.data.length) {
    info.pathStartY = info.data[0].y + 3 * info.rectWidth + 32;
  }
  if (!info.pathEndY && info.data && info.data.length) {
    // 轨迹圆的间距
    info.pathEndY = info.pathStartY + 50;
  }
  if (!info.arcRadius && info.pathEndY && info.pathStartY) {
    // 轨迹圆的半径
    info.arcRadius = 25;

    info.arcLocationY = info.pathStartY + 25;
  }
};

const drawInitRects = () => {
  const width = info.width / (info.data.length * 2); // 盒子宽度
  info.rectWidth = width;
  const spacingX = 40; // 左边距
  const spacingY = 20; // 上边距
  const distanceW = 3.8;

  const newData = info.data.map((item, idx) => {
    // 下面数据 rect的中心坐标
    let type;
    if (idx + 1 > info.divideCount) {
      item.x = spacingX + width * (info.data.length - 1 - idx) * distanceW;
      item.y = info.pathEndY + info.rectWidth + 16;
      type = "down";
    }
    // 上面数据
    if (idx < info.divideCount) {
      item.x = spacingX + info.rectWidth * distanceW * idx;
      item.y = spacingY + info.rectWidth - 16;
      type = "up";

      if (idx === 0) {
        initPathInfo();
      }
      if (idx + 1 === info.divideCount) {
        info.maxDistance = item.x - info.data[0].x;
      }
    }

    const target = {
      startX: item.x,
      startY: item.y,
      endX: info.radius,
      endY: info.radius,
      fillStyle: "#fff",
      strokeStyle: "#fff",
      type,
    };

    if (!item.isEmpty) {
      info.rects[idx] = target;
    }

    const triangleInfo = {
      x: item.x + info.halfRadius,
      y: item.y + (idx < info.divideCount ? info.radius : 0),
      fillStyle: "#fff",
      direct: idx < info.divideCount ? "down" : "up",
    };
    if (!item.isEmpty) {
      info.triangles[idx] = triangleInfo;
    }

    const tagLen = getPartLen(idx + 1);
    const tagTexts = {
      startX:
        item.x +
        (0.4 * info.radius - info.radius / 4) / 2 +
        (tagLen > 1 ? -1 : 1),
      startY: item.y - 0.2 * info.radius,
      text: `${item.stationNo}`,
      fillStyle: "#fff",
      fontSize: info.radius / 4,
    };
    if (!item.isEmpty) {
      info.tagTexts[idx] = tagTexts;
    }

    const tagInfo = {
      startX: item.x,
      startY: item.y,
      endX: 0.4 * info.radius,
      endY: 0.4 * info.radius,
      fillStyle: "#1890ff",
      strokeStyle: "#1890ff",
    };
    if (!item.isEmpty) {
      info.tags[idx] = tagInfo;
    }
    return item;
  });

  info.data = newData;
};

const reDraw = () => {
  clear();
  cancelAnimationFrame(info.raf);
  init();

  if (info.data?.length > 0) {
    drawInitRects();
    animate();
  }
};

// 数据处理
const handleData = (cData) => {
  try {
    // console.log(cData, "---cData---");
    // const res = await axios.postAction(
    //   "/api/mo/mo-simulator-proc-roadmap/listAllStationAndProc",
    //   params
    // );

    // 一行的站位数
    info.divideCount = Math.ceil(cData.length / 2);
    // 一个格子的宽度
    info.radius = (info.width - 60) / info.divideCount / 1.5;
    // 一个格子的半个宽度
    info.halfRadius = info.radius / 2;
    // 画布的高度 100 轨道路径的高度
    info.height = info.radius * 4 + 100;

    info.data =
      cData.length % 2 === 0
        ? cData
        : [
            ...cData,
            {
              parts: [],
              color: "transparent",
              isEmpty: true,
              proOfCircleVOList: [],
              stationNo: cData.length,
            },
          ];
    // 计算最大圈数
    info.maxCircle = info.data.reduce((prev, item) => {
      const children = item.proOfCircleVOList;
      const childrenCircles = children.reduce((prev, item) => {
        prev.push(item.circle);
        return prev;
      }, []);
      const max = Math.max(...childrenCircles);
      // max
      return Math.max(prev, max);
    }, 0);
    const canvas = document.getElementById(props.id);
    info.ctx = canvas.getContext("2d");

    info.ctx.fillRect(0, 0, info.width, info.height);

    reDraw();
    drawInitBackgroundLine();
  } catch (err) {
    console.log(err);
  }
};
watch(
  () => props.data,
  (newData) => {
    // console.log(newData, "----cavansPath-----");
    if (newData?.length > 0) {
      info.data = [];
      info.curLocation = undefined;
      info.curParts = "";
      info.index = 0;
      info.circleCount = 1;
      // reDraw();
      handleData(newData);
    } else {
      info.data = [];
      info.curLocation = undefined;
      info.curParts = "";
      info.index = 0;
      info.circleCount = 1;
      reDraw();
    }
    // try {
    //   console.log(params);
    //   // const res = await axios.postAction(
    //   //   "/api/mo/mo-simulator-proc-roadmap/listAllStationAndProc",
    //   //   params
    //   // );

    //   // 一行的站位数
    //   info.divideCount = Math.ceil(res.data.length / 2);
    //   // 一个格子的宽度
    //   info.radius = (info.width - 60) / info.divideCount / 1.5;
    //   // 一个格子的半个宽度
    //   info.halfRadius = info.radius / 2;
    //   // 画布的高度 100 轨道路径的高度
    //   info.height = info.radius * 4 + 100;

    //   info.data =
    //     res.data.length % 2 === 0
    //       ? res.data
    //       : [
    //           ...res.data,
    //           {
    //             parts: [],
    //             color: "transparent",
    //             isEmpty: true,
    //             proOfCircleVOList: [],
    //             stationNo: res.data.length,
    //           },
    //         ];
    //   // 计算最大圈数
    //   info.maxCircle = info.data.reduce((prev, item) => {
    //     const children = item.proOfCircleVOList;
    //     const childrenCircles = children.reduce((prev, item) => {
    //       prev.push(item.circle);
    //       return prev;
    //     }, []);
    //     const max = Math.max(...childrenCircles);
    //     // max
    //     return Math.max(prev, max);
    //   }, 0);
    //   const canvas = document.getElementById(props.id);
    //   info.ctx = canvas.getContext("2d");

    //   info.ctx.fillRect(0, 0, info.width, info.height);

    //   reDraw();
    //   drawInitBackgroundLine();
    // } catch (err) {
    //   console.log(err);
    // }
  },
  {
    deep: true,
    immediate: true,
  }
);

onMounted(async () => {
  console.log(props, "===");
});

defineExpose({
  reDraw,
});
</script>

<template>
  <div class="partsHeader">
    <div>{{$t('components.nowCircle')}}: {{ info.circleCount }}</div>
    <div class="partsRight">
      <div class="partsRightItem">{{$t('components.nowStation')}}: {{ info.curLocation }}</div>
      <div class="partsRightItem">{{$t('components.stationProcess')}}: {{ info.curParts }}</div>
    </div>
  </div>
  <canvas
    class="canvas"
    :id="props.id"
    :width="info.width"
    :height="info.height"
  ></canvas>
</template>

<style>
.partsHeader {
  display: flex;
  justify-content: space-between;
  padding: 16px;
  font-size: 16px;
}

.partsRight {
  display: flex;
}

.partsRightItem {
  margin-left: 24px;
}

.config {
  display: flex;
  flex-direction: column;
}

.canvas {
  filter: drop-shadow(4px 4px 8px rgba(0, 0, 0, 0.2));
}
</style>
